package com.liqi.web.controller.items;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.liqi.common.annotation.Log;
import com.liqi.common.core.controller.BaseController;
import com.liqi.common.core.domain.AjaxResult;
import com.liqi.common.core.domain.R;
import com.liqi.common.core.page.TableDataInfo;
import com.liqi.common.enums.BusinessType;
import com.liqi.common.utils.DateUtils;
import com.liqi.common.utils.StringUtils;
import com.liqi.common.utils.poi.ExcelUtil;
import com.liqi.common.utils.uuid.GenerateCodeUtils;
import com.liqi.device.domain.dto.ExcludeSubjectInfo;
import com.liqi.items.domain.TCfgService;
import com.liqi.items.domain.TCfgSubject;
import com.liqi.items.domain.TRelServiceBranch;
import com.liqi.items.domain.VO.RelServiceVO;
import com.liqi.items.domain.VO.ServiceVO;
import com.liqi.items.domain.VO.TCfgServiceBranchAddVo;
import com.liqi.items.domain.VO.TCfgServiceBranchVO;
import com.liqi.items.domain.VO.TCfgServiceVO;
import com.liqi.items.mapper.TCfgServiceMapper;
import com.liqi.items.service.ITCfgServiceService;
import com.liqi.items.service.ITCfgSubjectService;
import com.liqi.items.service.ITRelServiceBranchService;
import com.liqi.items.service.ITRelServiceSubjectService;
import com.liqi.sms.utils.SmartHttp;
import com.liqi.sms.utils.TokenUtil;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * 事项Controller
 *
 * @author ruoyi
 * @date 2022-04-08
 */
@Api(tags = "事项管理")
@RestController
@RequestMapping("/items/service")
public class TCfgServiceController extends BaseController {

	// 编程式事务
	@Autowired
	private TransactionTemplate transactionTemplate;

	@Autowired
	private ThreadPoolTaskExecutor poolTaskExecutor;

	@Autowired
	private ITCfgServiceService tCfgServiceService;

	@Autowired
	private TCfgServiceMapper tCfgServiceMapper;

	@Autowired
	private ITCfgSubjectService tCfgSubjectService;

	@Autowired
	private ITRelServiceSubjectService tRelServiceSubjectService;

	@Autowired
	private ITRelServiceBranchService tRelServiceBranchService;
	@Value("${MiddlePlatform.Url}")
	private String middlePlatformUrl;

	@Value("${MiddlePlatform.TokenUsername}")
	private String tokenUsername;

	@Value("${MiddlePlatform.TokenPassWord}")
	private String tokenPassWord;

	/**
	 * 查询事项列表
	 */
	@PreAuthorize("@ss.hasPermi('items:service:list')")
	@GetMapping("/list")
	public TableDataInfo list(TCfgService tCfgService) {
		startPage();
		List<TCfgService> list = tCfgServiceService.selectTCfgServiceList(tCfgService);
		return getDataTable(list);
	}

	/**
	 * 导出事项列表
	 */
	@PreAuthorize("@ss.hasPermi('items:service:export')")
	@Log(title = "事项", businessType = BusinessType.EXPORT)
	@PostMapping("/export")
	public void export(HttpServletResponse response, TCfgService tCfgService) {
		List<TCfgService> list = tCfgServiceService.selectTCfgServiceList(tCfgService);
		ExcelUtil<TCfgService> util = new ExcelUtil<TCfgService>(TCfgService.class);
		util.exportExcel(response, list, "事项数据");
	}

	/**
	 * 获取事项详细信息
	 */
	@PreAuthorize("@ss.hasPermi('items:service:query')")
	@GetMapping(value = "/{id}")
	public AjaxResult getInfo(@PathVariable("id") Long id) {
		return AjaxResult.success(tCfgServiceService.selectTCfgServiceById(id));
	}

	/**
	 * 新增事项
	 */
	@PreAuthorize("@ss.hasPermi('items:service:add')")
	@Log(title = "事项", businessType = BusinessType.INSERT)
	@PostMapping
	@ApiOperation("新增事项")
	public AjaxResult add(@RequestBody TCfgService tCfgService) {
		if (tCfgService.getBranchCodes() != null && tCfgService.getBranchCodes().length > 0) {
			tCfgService.setServiceCode(GenerateCodeUtils.getSequnce());
			tCfgService.setCreateBy(getUsername());
			tCfgService.setStatus(0);
			int num = tCfgServiceService.insertTCfgService(tCfgService);
			// 网点编码
			String[] branchCodes = tCfgService.getBranchCodes();
			int total = branchCodes.length;
			// 构建一个list进行批量插入传参
			List<TCfgService> list = tCfgServiceService.getServiceList(tCfgService, branchCodes);
			tCfgServiceService.batchServiceAndBranch(list);
			return AjaxResult.success("成功插入" + total + "条关联数据");
		} else {
			tCfgService.setServiceCode(GenerateCodeUtils.getSequnce());
			tCfgService.setCreateBy(getUsername());
			tCfgService.setStatus(0);
			tCfgServiceService.insertTCfgService(tCfgService);
			TCfgService serviceEntityById = tCfgServiceMapper.getServiceEntityById(tCfgService.getId());
			return AjaxResult.success(serviceEntityById);
		}
	}

	/**
	 * 修改事项
	 */
	@PreAuthorize("@ss.hasPermi('items:service:edit')")
	@Log(title = "事项", businessType = BusinessType.UPDATE)
	@PutMapping
	public AjaxResult edit(@RequestBody TCfgService tCfgService) {
		if (tCfgService.getServiceCode() != null && tCfgService.getServiceCode().length() > 0) {
			String ServiceCode = tCfgService.getServiceCode();
			tCfgService.setUpdateBy(getUsername());
			tCfgService.setUpdateTime(DateUtils.getNowDate());
			int num = tCfgServiceService.updateTCfgService(tCfgService);
			// 删除原有关联
		//	int del = tCfgServiceService.deleteBranchsByServiceCode(tCfgService.getServiceCode());
			// 构建一个list进行批量插入传参
//            List <TCfgService> list = tCfgServiceService.getServiceList(tCfgService,branchCodes);
//            tCfgServiceService.batchServiceAndBranch(list);
			return AjaxResult.success("修改正常");
		} else {
//            return toAjax(tCfgServiceService.insertTCfgService(tCfgService));
			return AjaxResult.error("修改异常");
		}
	}

	/**
	 * 删除事项
	 */
	@PreAuthorize("@ss.hasPermi('items:service:remove')")
	@Log(title = "事项", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
	@Transactional
	public AjaxResult remove(@PathVariable Long[] ids) {
		// todo 这里要调中台删除关联事项
		String updateBy = getUsername();
		Date updateTime = DateUtils.getNowDate();
		Map<String, Object> map = new HashMap<>();
		map.put("updateBy", updateBy);
		map.put("updateTime", updateTime);
		map.put("ids", ids);
		// 清除关联表相关事项网点关联
		tCfgServiceService.batchDeleteServiceandBranch(ids);
		tCfgServiceService.SoftdeleteTCfgServiceByIds(map);
		// 调用中台解除关联事项
		List<String> serviceCodes = tCfgServiceService.getServiceByIds(ids);
		Map<String, String> heardMap = new HashMap<>();
		heardMap.put("Authorization", TokenUtil.getToken(middlePlatformUrl + "auth/token", tokenUsername, tokenPassWord));
		serviceCodes.forEach(m ->{
			Map<String, String> hashMap = new HashMap<>();
			hashMap.put("relFlag", "2");
			hashMap.put("serviceCode", m);
			String json = JSON.toJSONString(hashMap);
			try {
				String body = SmartHttp.sendPostJson(middlePlatformUrl + "service/selfService/relService", json, heardMap);
				JSONObject jsonObject = JSON.parseObject(body);
				if ((Integer)jsonObject.get("code") != 200){
					throw new RuntimeException("调用中台出错。关联失败");
				}
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException(e.getMessage());
			}
		});
		return AjaxResult.success();
	}

	/**
	 * 获取关联事项
	 */
	/*
	 * @GetMapping("/getRelevanceItem") public TableDataInfo
	 * relevanceItem(@RequestParam("serviceName") String serviceName){ long start =
	 * System.currentTimeMillis(); List<String> serviceCodeList =
	 * tCfgServiceService.selectServiceCode(); String serviceCode =
	 * StringUtils.join(serviceCodeList,","); startPage(); List<Map<String, Object>>
	 * list = new ArrayList<>(); list =
	 * tCfgServiceService.selectReactTCfgServiceListFilterByRelation(serviceName,
	 * serviceCode); logger.info("总耗时"+ (System.currentTimeMillis() - start));
	 * return getDataTable(list); }
	 */

	/*
	 * @GetMapping("/getRelevanceItem") public TableDataInfo relevanceItem(){ long
	 * start = System.currentTimeMillis();
	 * 
	 * //先查找设备库已有的关联事项编码 String[] reactServiceCodesExist =
	 * tCfgServiceService.selectReactTCfgServiceCodesExistInDeviceDB();
	 * logger.info("查找已有事项编码耗时"+(System.currentTimeMillis() - start));
	 * //获取事项时过滤，已添加到设备管理后台的不获取 startPage(); List<Map<String, Object>> list = new
	 * ArrayList<>(); if (reactServiceCodesExist.length > 0){ list =
	 * tCfgServiceService.selectReactTCfgServiceListFilterByServiceCodes(
	 * reactServiceCodesExist); logger.info("过滤事项编码耗时"+(System.currentTimeMillis() -
	 * start)); }else { list = tCfgServiceService.selectReactTCfgServiceList();
	 * logger.info("普通查找事项编码耗时"+(System.currentTimeMillis() - start)); }
	 * logger.info("总耗时"+ (System.currentTimeMillis() - start)); return
	 * getDataTable(list); }
	 */

	/**
	 * 关联事项的批量添加和网点关联 多对多
	 *
	 */
	@PostMapping("/batchOutsideServices")
	public AjaxResult batchOutsideServices(@RequestBody TCfgServiceVO tCfgServiceVO) {
		// todo 这里要调关联事项
		// 将接收到的远程数据库批量插入本地事项库
		if (!tCfgServiceVO.getServices().isEmpty()) {
			// 事项编码
			List<String> collect = tCfgServiceVO.getServices().stream().map(m -> m.getServiceCode()).collect(Collectors.toList());
			transactionTemplate.executeWithoutResult(new Consumer<TransactionStatus>() {
				@Override
				public void accept(TransactionStatus transactionStatus) {
					for (TCfgService tCfgService :tCfgServiceVO.getServices()) {
						// 判断表里面是否存在对应编码数据
						Integer count = tCfgServiceService.count(tCfgService.getServiceCode());
						if (count > 0) {
							tCfgService.setUpdateBy(getUsername());
							tCfgService.setUpdateTime(DateUtils.getNowDate());
							tCfgService.setStatus(0);
							tCfgServiceService.updateByServiceCode(tCfgService);
						}else {
							// 先将每个远程事项库的事项插入本地数据库表
							tCfgService.setCreateBy(getUsername());
							tCfgService.setCreateTime(DateUtils.getNowDate());
							tCfgService.setStatus(0);
							tCfgServiceService.insertTCfgService(tCfgService);
						}
						// 然后每个事项跟相对应的网点关联起来插入关联表
						// 修改远程库的relation关联状态 所需要的 mybatis参数
						/*
						 * Map<String, String> map = new HashMap<>(); map.put("relation","1"); //
						 * 0是没有关联， 1是 已经关联 map.put("serviceCode", tCfgService.getServiceCode());
						 * tCfgServiceService.relationTCfgService(map);
						 */
					}
				}
			});

			// 这里使用异步调用中台
			Map<String, String> heardMap = new HashMap<>();
			heardMap.put("Authorization", TokenUtil.getToken(middlePlatformUrl + "auth/token", tokenUsername, tokenPassWord));
			collect.forEach(m ->{
				CompletableFuture.runAsync(() -> { HashMap<String, String> hashMap = new HashMap<>();
				hashMap.put("relFlag", "1");
				hashMap.put("serviceCode", m);
				String json = JSON.toJSONString(hashMap);
				try {
					String body = SmartHttp.sendPostJson(middlePlatformUrl + "service/selfService/relService",json, heardMap);
				} catch (Exception e) {
					logger.error("与中台关联事项出错::事项编码为:{}",m);
					e.printStackTrace();
				}
				}, poolTaskExecutor);
			});

			return AjaxResult.success("批量添加完成");
		} else {
			return AjaxResult.error("请勾选相对应的远程事项进行添加");
		}
	}

	/**
	 * 批量删除事项和网点的关联关系 多对多
	 *
	 */
	@ApiOperation("批量删除事项和网点的关联关系")
	@PreAuthorize("@ss.hasPermi('items:service:deleteServiceBranchRelation')")
	@Log(title = "删除事项网点关联", businessType = BusinessType.DELETE)
	@PostMapping("/deleteServiceBranchRelation")
	public AjaxResult deleteServiceBranchRelation(@RequestBody TCfgServiceBranchVO tCfgServiceBranchVO) {

		String branchCode = tCfgServiceBranchVO.getBranchCode();
		List<String> serviceCodeList = tCfgServiceBranchVO.getServiceCodeList();
		String[] serviceCodes = serviceCodeList.toArray(new String[serviceCodeList.size()]);
		// 1.删除事项与网点关联关系
		Map<String, Object> map = new HashMap();
		map.put("branchCode", branchCode);
		map.put("serviceCodes", serviceCodes);
		tCfgServiceService.deleteServiceBranchInServiceCodes(map);
		// 2.根据查找网点对应的主题
		List<TCfgSubject> subjects = tCfgSubjectService.selectTCfgSubjectByBranchCode(branchCode);
		List<String> subjectCodes = new ArrayList<>();
		for (TCfgSubject tCfgSubject : subjects) {
			subjectCodes.add(tCfgSubject.getSubjectCode());
		}
		// 3.删除主题的对应事项主题关联关系
		for (String serviceCode : serviceCodeList) {
			Map<String, Object> paramsMap = new HashMap<>();
			paramsMap.put("serviceCode", serviceCode);
			paramsMap.put("subjectCodes", subjectCodes);
			tRelServiceSubjectService.deleteTRelServiceSubjectBySubjectCode(paramsMap);
		}
		return AjaxResult.success("批量删除完成");
	}

	/**
	 * 批量添加事项和网点的关联关系 多对多
	 *
	 */
	@ApiOperation("批量添加事项和网点的关联关系")
	@PreAuthorize("@ss.hasPermi('items:service:addServiceBranchRelation')")
	@Log(title = "添加事项和网点的关联关系", businessType = BusinessType.INSERT)
	@PostMapping("/addServiceBranchRelation")
	public AjaxResult addServiceBranchRelation(@RequestBody TCfgServiceBranchAddVo tCfgServiceBranchAddVo) {
		/*
		 * String branchCode = tCfgServiceBranchAddVo.getBranchCode(); String[]
		 * branchCodes = {branchCode}; List<TCfgService> serviceList =
		 * tCfgServiceBranchAddVo.getServiceList(); List <TCfgService> list = new
		 * ArrayList<>(); for (TCfgService tCfgService : serviceList){ List<TCfgService>
		 * services = tCfgServiceService.getServiceList(tCfgService,branchCodes);
		 * list.addAll(services); } return
		 * toAjax(tCfgServiceService.batchServiceAndBranch(list));
		 */
		String branchCode = tCfgServiceBranchAddVo.getBranchCode();
		List<TCfgService> serviceList = tCfgServiceBranchAddVo.getServiceList();
		for (TCfgService tCfgService : serviceList) {
			TRelServiceBranch tRelServiceBranch = new TRelServiceBranch();
			tRelServiceBranch.setCreateTime(DateUtils.getNowDate());
			tRelServiceBranch.setUpdateTime(DateUtils.getNowDate());
			tRelServiceBranch.setCreateBy(getUsername());
			tRelServiceBranch.setUpdateBy(getUsername());
			tRelServiceBranch.setBranchCode(branchCode);
			tRelServiceBranch.setServiceCode(tCfgService.getServiceCode());
			tRelServiceBranch.setStatus("0");
			tRelServiceBranchService.insertTRelServiceBranch(tRelServiceBranch);
		}
		return AjaxResult.success("批量关联完成");
	}

	/**
	 * 通过网点编码 查询事项列表
	 *
	 * @param branchCode
	 * @return
	 */
	@GetMapping("/listServiceInBranch")
	public TableDataInfo listServiceInBranch(TCfgService tCfgService) {
		startPage();
		List<TCfgService> list = tCfgServiceService.selectTCfgServiceByBranchCode(tCfgService);
		return getDataTable(list);
	}

	/**
	 * 通过排除关联的网点编码 查询事项列表
	 * 
	 * @return
	 */
	@GetMapping("/listServiceNotInBranch")
	public TableDataInfo listServiceNotInBranch(ExcludeSubjectInfo excludeSubjectInfo) {
		String branchCode = excludeSubjectInfo.getBranchCode();
		String serviceName = excludeSubjectInfo.getServiceName();
		String deptName = excludeSubjectInfo.getDeptName();
		startPage();
		List<TCfgService> list = tCfgServiceService.selectTCfgServiceListExcludeExistBranchCode(branchCode,
				serviceName,deptName);
		return getDataTable(list);
	}
	/**
	 * 复制网点事项树
	 *
	 * @return
	 */
	@ApiOperation("复制网点事项树")
	@PostMapping("/copyBranch")
	public R copyBranch(@RequestParam("oldBranchCode")String oldBranchCode,@RequestParam("newBranchCode")String newBranchCode) {
		TRelServiceBranch tRelServiceBranch=new TRelServiceBranch();
		tRelServiceBranch.setBranchCode(oldBranchCode);
		tRelServiceBranch.setStatus("0");
		List<TRelServiceBranch> oldBranchList= tRelServiceBranchService.selectTRelServiceBranchList(tRelServiceBranch);


		for(TRelServiceBranch oldBranchInfo: oldBranchList){
			TRelServiceBranch relServiceBranch=new TRelServiceBranch();
			relServiceBranch.setBranchCode(newBranchCode);
			relServiceBranch.setServiceCode(oldBranchInfo.getServiceCode());
			relServiceBranch.setStatus("0");
			TRelServiceBranch tRelServiceBranch1 = tRelServiceBranchService.selectTRelServiceBranchByServiceCode(relServiceBranch);
			if(tRelServiceBranch1==null){
				TRelServiceBranch tRelServiceBranch2=new TRelServiceBranch();
					tRelServiceBranch2.setServiceCode(oldBranchInfo.getServiceCode());
					tRelServiceBranch2.setBranchCode(newBranchCode);
					tRelServiceBranch2.setCreateBy(getUsername());
					tRelServiceBranch2.setUpdateBy(getUsername());
				    tRelServiceBranchService.insertTRelServiceBranch(tRelServiceBranch2);
			}
		}
		return R.ok();
	}

	/**
	 * 查询出未关联的事项
	 */
	@ApiOperation("查询出未关联的事项")
	/* @PreAuthorize("@ss.hasPermi('items:subject:listExcludeSubject')") */
	@RequestMapping(value = "/getRelevanceItem", method = RequestMethod.POST)
	public R getRelevanceItem(@RequestBody ServiceVO serviceVO) {
		if (StringUtils.isBlank(serviceVO.getPageSize().toString())
				&& StringUtils.isBlank(serviceVO.getPageNum().toString())) {
			return R.fail("pageNum,pageSize不能为空！");
		}
		
		//只查询没有关联的事项
		serviceVO.setIsRel("1");
		//只查询已经发布的事项
		serviceVO.setIsPublish("1");

		JSONObject jsonObject = (JSONObject) JSONObject.toJSON(serviceVO);
		Map<String, String> heardMap = new HashMap<>();
		heardMap.put("Authorization",
				TokenUtil.getToken(middlePlatformUrl + "auth/token", tokenUsername, tokenPassWord));
		Map<String, Object> resultmap = new HashMap();
		try {
			String json = SmartHttp.sendPostJson(middlePlatformUrl + "service/cfgService/queryServiceList",
					jsonObject.toString(), heardMap);
			JSONObject repJson = JSONObject.parseObject(json);
			Integer code = (Integer) repJson.get("code");
			if (200 != code) {
				String msg = repJson.get("msg").toString();
				return R.fail(msg);
			}
			Map rspData = (Map) repJson.get("data");
			if (rspData != null) {
				String aString = rspData.get("rows").toString();
				List<TCfgService> tCfgServicesList = JSON.parseArray(aString, TCfgService.class);
				resultmap.put("total", rspData.get("total"));
				resultmap.put("tCfgServicesList", tCfgServicesList);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return R.ok(resultmap);
	}

	/**
	 * 自助服务关联或取消关联事项
	 */
//	@ApiOperation(" 自助服务关联或取消关联事项")
//	@RequestMapping(value = "/relService", method = RequestMethod.POST)
//	public R relService(@RequestBody List<RelServiceVO> relServiceVO) {
//
//		Map<String, Object> resultmap = new HashMap();
//		RelServiceVO rVo = new RelServiceVO();
//		for (RelServiceVO rel : relServiceVO) {
//			String relFlag = rel.getRelFlag();
//			String serviceCode = rel.getServiceCode();
//			if (StringUtils.isBlank(relFlag) && StringUtils.isBlank(serviceCode)) {
//				return R.fail("formKey,relFlag不能为空！");
//			} else {
//				rVo.setServiceCode(serviceCode);
//				rVo.setRelFlag(relFlag);
//			}
//			JSONObject reqJson = (JSONObject) JSONObject.toJSON(rVo);
//			Map<String, String> heardMap = new HashMap<>();
//			heardMap.put("Authorization", TokenUtil.getToken(middlePlatformUrl + "auth/token", tokenUsername, tokenPassWord));
//			try {
//				String json = SmartHttp.sendPostJson(middlePlatformUrl + "service/selfService/relService",
//						reqJson.toString(), heardMap);
//				JSONObject repJson = JSONObject.parseObject(json);
//				Integer code = (Integer) repJson.get("code");
//				String msg = repJson.get("msg").toString();
//				if (200 != code) {
//					return R.fail(msg);
//				}
//				String rspData = repJson.get("data") == null ? "" : repJson.get("data").toString();
//				resultmap.put("data", rspData);
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
//		}
//		return R.ok(resultmap);
//	}
}
